home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Orlando_1993 / Devcon93.4 / CAMD / examples / oldexamples / smf / smf.c next >
Encoding:
C/C++ Source or Header  |  1993-01-12  |  25.9 KB  |  845 lines

  1. ;/* 
  2. LC -b1 -icamd:include -cfist -v -j73 smf.c
  3. blink FROM LIB:c.o smf.o TO smf LIB LIB:lc.lib LIB:amiga.lib
  4. quit
  5. */
  6.  
  7. /*=======================================================================
  8.  
  9. This file is a prototype score player which reads standard MIDI files,
  10. format type 0 or 1.  It conforms to the 1.0 specification for standard 
  11. MIDI files by Dave Oppenheim of Opcode Systems.  It uses both the CAMD and 
  12. RealTime libraries by Roger Dannenberg, David Joiner, et al.
  13.  
  14. Design and coding by Dan Baker, Commodore Business Machines.
  15.  
  16. The tempo handling used by this program is crude and is known to have 
  17. deficiencies.  It should not be used as an example of  proper tempo handling.  
  18. This program also makes extensive use of globals and other techniques which 
  19. are convenient to the program's author.  Apologies to the reader.
  20. =======================================================================*/
  21.  
  22. /* System Include Files */
  23. #include <exec/types.h>
  24. #include <exec/memory.h>
  25. #include <libraries/dosextens.h>
  26.  
  27. /* CAMD MIDI Library Includes */
  28. #include <clib/camd_protos.h>
  29. #include <midi/camd.h>
  30. #include <midi/camdbase.h>
  31. #include <pragmas/camd_pragmas.h>
  32.  
  33. /* CAMD Real Time Library Includes */
  34. #include <clib/realtime_protos.h>
  35. #include <midi/realtime.h>
  36. #include <midi/realtimebase.h>
  37. #include <pragmas/realtime_pragmas.h>
  38.  
  39. /* System function prototypes */
  40. #include <clib/exec_protos.h>
  41. #include <clib/dos_protos.h>
  42.  
  43. /* Lattice Standard I/O */
  44. #include <latticei:stdlib.h>
  45. #include <latticei:stdio.h>
  46.  
  47. #ifdef LATTICE
  48. int CXBRK(void) { return(0); }     /* Disable Lattice CTRL/C handling */
  49. int chkabort(void) { return(0); }  /* really */
  50. #endif
  51.  
  52.  
  53. /*-------------------*/
  54. /*     Prototypes    */
  55. /*-------------------*/
  56. void kill(char *killstring);
  57. ULONG ComVarLen (UBYTE *value);
  58. UBYTE *DecodeEvent(UBYTE *,struct SMFTrack *, ULONG);
  59. LONG transfer(struct SMFTrack *,ULONG,LONG);
  60. ULONG changetempo(ULONG);
  61.  
  62.  
  63.  
  64. /*---------------------*/
  65. /* S M F  Header  File */
  66. /*---------------------*/
  67. /* Four-character IDentifier builder*/
  68. #define MakeID(a,b,c,d)  ( (LONG)(a)<<24L | (LONG)(b)<<16L | (c)<<8 | (d) )
  69. #define MThd MakeID('M','T','h','d')
  70. #define MTrk MakeID('M','T','r','k')
  71.  
  72. struct SMFHeader {LONG     ChunkID;  /* 4 ASCII characters */
  73.                   LONG     VarLeng;
  74.                   WORD     Format;
  75.                   UWORD    Ntrks;
  76.                   WORD     Division;
  77.                  };
  78.  
  79.  
  80. struct DecTrack { ULONG absdelta;   /* 32-bit delta */
  81.                   ULONG nexclock;   /* storage */
  82.                   UBYTE status;     /* status from file */
  83.                   UBYTE rstatus;    /* running status from track */
  84.                   UBYTE d1;         /* data byte 1 */
  85.                   UBYTE d2;         /* data byte 2 */
  86.                   ULONG absmlength; /* 32-bit absolute metalength */
  87.                   UBYTE *endmarker;
  88.                   UBYTE metatype;   /* meta event type */
  89.                   BOOL playable;
  90.                   UBYTE pad3;
  91.                 };
  92.  
  93. /*------------------*/
  94. /* MIDI Header File */
  95. /*------------------*/
  96. #define MAXTRAX 16L
  97. #define TWOxMAXTRAX 32L
  98. #define MIDIBUFSIZE 512L
  99.  
  100.  
  101. /* Library Bases */
  102. struct Library  *CamdBase,
  103.                 *RealTimeBase;
  104.  
  105. /* Compiler glue: stub functions for camd.library */
  106. struct MidiNode *CreateMidi(Tag tag, ...)
  107. {    return CreateMidiA((struct TagItem *)&tag );
  108. }
  109.  
  110. BOOL SetMidiAttrs(struct MidiNode *mi, Tag tag, ...)
  111. {    return SetMidiAttrsA(mi, (struct TagItem *)&tag );
  112. }
  113.  
  114. struct MidiLink *AddMidiLink(struct MidiNode *mi, LONG type, Tag tag, ...)
  115. {    return AddMidiLinkA(mi, type, (struct TagItem *)&tag );
  116. }
  117.  
  118.  
  119. /* Compiler glue: stub functions for realtime.library */
  120. BOOL SetPlayerAttrs(struct PlayerInfo *pi, Tag tag, ...)
  121. {    return SetPlayerAttrsA(pi, (struct TagItem *)&tag );
  122. }
  123.  
  124. struct PlayerInfo *CreatePlayer(Tag tag, ...)
  125. {    return CreatePlayerA( (struct TagItem *)&tag );
  126. }
  127.  
  128.  
  129. /*--------------*/
  130. /*   Globals    */
  131. /*--------------*/
  132. struct MidiLink   *pMidiLink;
  133. struct MidiNode   *pMidiNode;
  134. struct PlayerInfo *pPlayerInfo;
  135. BPTR               smfhandle;
  136. UBYTE             *smfdata,*ptrack[TWOxMAXTRAX],*pData,trackct;
  137. LONG               midiSignal,smfdatasize,fillclock[2];
  138. ULONG              oldclock,sizeDTrack,tfactor,division,donecount;
  139. UBYTE             *pfillbuf[2],lastRSchan;
  140.  
  141.  
  142.  
  143. /*-----------------------------*/
  144. /*     CODE  Starts  Here      */
  145. /*-----------------------------*/
  146.  
  147. ULONG
  148. ComVarLen (value)
  149. UBYTE *value;
  150. {
  151.    register ULONG newval;
  152.    register UBYTE x;
  153.  
  154.    x=0;newval=0L;
  155.    while(x<4)
  156.    {
  157.       newval <<= 7;
  158.       newval |=  *(value+x) & 0x7f;
  159.       if(*(value+x) < 0x80)x=4;
  160.       x++;
  161.    }
  162.    return(newval);
  163. }
  164.  
  165.  
  166. void
  167. main(int argc, char **argv)
  168. {
  169.    char              *smfname,iobuffer[14];
  170.    struct SMFHeader  *pSMFHeader;
  171.    UBYTE             *pbyte,x;
  172.    WORD               w;
  173.    LONG               rdcount,y,z,res;
  174.    BOOL               notdone,timerr;
  175.    ULONG              masterswitch,lowclock,
  176.                       ylength[2],wakeup;
  177.  
  178.    BYTE               oldpri; /* Priority to restore */
  179.    struct Task       *mt;     /* Pointer to this task */
  180.  
  181.    UBYTE fillbuf1[MIDIBUFSIZE]; /* These buffers hold the notes translated */
  182.    UBYTE fillbuf2[MIDIBUFSIZE]; /* from the SMF file for playback          */
  183.    struct DecTrack *pDTrack[MAXTRAX];
  184.  
  185.    oldclock=0L;
  186.    smfdata=NULL;
  187.    smfhandle=0;
  188.    pMidiLink=NULL;
  189.    pMidiNode=NULL;
  190.    pPlayerInfo=NULL;
  191.    RealTimeBase=NULL;
  192.    CamdBase=NULL;
  193.    mt=NULL;
  194.    notdone=TRUE;
  195.    pfillbuf[0]=fillbuf1;
  196.    pfillbuf[1]=fillbuf2;
  197.    fillclock[0]=0L;
  198.    fillclock[1]=0L;
  199.    donecount=0L;
  200.    lastRSchan=0xf1; /* Status of $F1 is undefined in Standard MIDI file Spec */
  201.    tfactor=12;
  202.  
  203.    /*--------------------------------------*/
  204.    /* Open the CAMD and RealTime libraries */
  205.    /*--------------------------------------*/
  206.    CamdBase=OpenLibrary("camd.library",0L);
  207.    if(!CamdBase)
  208.       kill("Can't open CAMD MIDI Library\n");
  209.  
  210.    RealTimeBase=OpenLibrary("realtime.library",0L);
  211.    if(!RealTimeBase)
  212.       kill("Can't open CAMD Real Time Library\n");
  213.  
  214.    /*---------------*/
  215.    /* Open the File */
  216.    /*---------------*/
  217.    if(argv[1]==NULL) 
  218.        kill("No file name given.\n");
  219.    smfname=argv[1];
  220.    smfhandle= Open( (UBYTE *)smfname , MODE_OLDFILE );
  221.    if(smfhandle==0)
  222.        kill("Cannot open file.\n");
  223.  
  224.  
  225.    /*-------------------------------*/
  226.    /* Read the SMF Header ID/Length */
  227.    /*-------------------------------*/
  228.    rdcount = Read(smfhandle,iobuffer,14);
  229.    if(rdcount==-1) 
  230.        kill ("Bad file during read.\n");
  231.    if(rdcount<14)  
  232.        kill ("Not an SMF file, too short.\n");
  233.  
  234.    /*-----------------*/
  235.    /* Evaluate Header */
  236.    /*-----------------*/
  237.    pSMFHeader=(struct SMFHeader *)iobuffer;
  238.    if (pSMFHeader->ChunkID != MThd ) 
  239.       kill("SMF file has unknown header ID.\n");
  240.  
  241.    if (pSMFHeader->VarLeng != 6 ) 
  242.       kill("SMF file has unknown header.\n");
  243.  
  244.    if (pSMFHeader->Format == 0 ) 
  245.       printf("Parsing SMF file format type 0\n");
  246.    else if (pSMFHeader->Format == 1 ) 
  247.       printf("Parsing SMF file format type 1\n");
  248.    else                          
  249.       kill("Can't parse this SMF file type.\n");
  250.  
  251.  
  252.    if(pSMFHeader->Ntrks >MAXTRAX )
  253.       kill("SMF file has more than MAXTRAX tracks.\n");
  254.    else
  255.       printf("SMF file has %ld tracks\n",pSMFHeader->Ntrks);
  256.  
  257.  
  258.    /*--------------------*/
  259.    /* Evaluate time base */
  260.    /*--------------------*/
  261.    if (pSMFHeader->Division < 0)
  262.    {
  263.       /* Real time: find frame rate */
  264.       w=(pSMFHeader->Division >> 8) & 0x007f;
  265.       if(w!=24 && w!=25 && w!=29 && w!=30)
  266.          kill("Non-metrical time specified; not MIDI/SMPTE frame rate\n");
  267.       else 
  268.          kill("Non-metrical time; MIDI/SMPTE frame rate\n");
  269.  
  270.       /* Real-time: find seconds resolution */
  271.       w=pSMFHeader->Division & 0x007f;
  272.       if(w==4)
  273.          kill("Non-metrical time in quarter seconds (MTC resolution)\n");
  274.       else if(w==8 || w==10 || w==80)
  275.          kill("Non-metrical time in 1/nths of a second (bit resolution)\n");
  276.       else
  277.          kill("Non-metrical time in 1/nths of a second\n");
  278.    }
  279.    else
  280.    {
  281.       printf("SMF file has 1/%ldth quarter notes per delta tick\n",
  282.               pSMFHeader->Division);
  283.       division=(ULONG)pSMFHeader->Division;
  284.  
  285.       /* According to "Standrd MIDI Files 1.0", July 1988, page 5 */
  286.       /* para. 4: "...time signature is assumed to be 4/4 and the */
  287.       /*           tempo 120 beats per minute."                   */
  288.       tfactor=changetempo(500000L); /* One quarter note every half second */
  289.    }
  290.  
  291.  
  292.    /*--------------------------------------*/
  293.    /* Calculate size and Read rest of file */
  294.    /*--------------------------------------*/
  295.    y = Seek(smfhandle,0L,OFFSET_END);
  296.    if(y==-1)
  297.       kill("SMF file or drive problem\n");
  298.    z = Seek(smfhandle,y,OFFSET_BEGINNING);
  299.    if(z==-1)
  300.       kill("SMF file or drive problem\n");
  301.  
  302.    smfdatasize=z-y; /* CDTV demo disk uses 12000 here */
  303.  
  304.    smfdata=AllocMem(smfdatasize,MEMF_PUBLIC | MEMF_CLEAR);
  305.    if(smfdata==NULL) 
  306.       kill("No memory for SMF file read.\n");
  307.  
  308.    rdcount = Read(smfhandle,smfdata,smfdatasize);
  309.    if(rdcount==-1)          
  310.       kill ("Bad file during read.\n");
  311.  
  312.    /* Commented out for CD ROM demo */
  313.    if(rdcount<smfdatasize)  
  314.       kill ("SMF file too short.\n");
  315.  
  316.  
  317.    /*----------------------*/
  318.    /* Find the MIDI tracks */
  319.    /*----------------------*/
  320.    trackct=0;
  321.    pbyte=smfdata;
  322.  
  323.    while((pbyte-smfdata < smfdatasize) && (trackct < MAXTRAX))
  324.    {
  325.       if((*pbyte=='M')&&(*(pbyte+1)=='T')&&
  326.          (*(pbyte+2)=='r')&&(*(pbyte+3)=='k'))
  327.       {
  328.          /* Beginning of track */
  329.          ptrack[trackct]=pbyte+8;
  330.          /* End of track marker */
  331.          ptrack[MAXTRAX+trackct-1]=pbyte;
  332.          trackct++;
  333.          pbyte+=4;
  334.       }
  335.       else pbyte++;
  336.    }
  337.  
  338.    /* End of track marker */   
  339.    ptrack[MAXTRAX+trackct-1]=pbyte;
  340.  
  341.    if(trackct != pSMFHeader->Ntrks)
  342.       kill("Too many or missing tracks\n");
  343.    printf("There are %ld tracks in this SMF file.\n",trackct);
  344.  
  345.  
  346.    /*----------------------------------------------*/
  347.    /* Set up a MidiNode and a MidiLink.  Link the  */
  348.    /* node to the default "out.0" MidiCluster .    */
  349.    /*----------------------------------------------*/
  350.    pMidiNode=CreateMidi( MIDI_Name,    "SMF Player",
  351.                          MIDI_MsgQueue, 0L,     /* This is a send-only   */
  352.                          MIDI_SysExSize,0L,     /* MIDI node so no input */
  353.                          TAG_END);              /* buffers are needed.   */
  354.    if(!pMidiNode)
  355.       kill("No memory for MIDI Node\n");
  356.  
  357.    pMidiLink=AddMidiLink( pMidiNode, MLTYPE_Sender, 
  358.                                      MLINK_Comment,  "SMF Player Link",
  359.                                      MLINK_Parse,    TRUE,
  360.                                      MLINK_Location, "out.0",
  361.                                      TAG_END);
  362.    if(!pMidiLink)
  363.       kill("No memory for MIDI Link\n");
  364.  
  365.  
  366.    /*----------------------------------------*/
  367.    /* Set up DTrack structure for each track */
  368.    /*----------------------------------------*/
  369.    sizeDTrack=trackct*sizeof(struct DecTrack);
  370.    pData=AllocMem( sizeDTrack, MEMF_PUBLIC | MEMF_CLEAR );
  371.    if(!pData)
  372.       kill("No memory for work area...\n");
  373.  
  374.    for(x=0;x<trackct;x++)
  375.    {
  376.       pDTrack[x]=(struct DecTrack *)
  377.                  (x * sizeof(struct DecTrack) + pData);
  378.       /* add end marker */
  379.       pDTrack[x]->endmarker = ptrack[MAXTRAX+x];
  380.    }
  381.  
  382.  
  383.    /*------------------------------------------------*/  
  384.    /* Get events from track into DecTrack structures */
  385.    /*------------------------------------------------*/
  386.    y=0;
  387.    masterswitch=0L;
  388.    lowclock=0xffffffff;
  389.  
  390.    /* Initialize DecTrack structures */
  391.    for(x=0;x<trackct;x++)
  392.    {  
  393.       /* Takes a pointer to the delta of a raw <MTrk event>, a pointer   */
  394.       /* to a DecTrack decoding structure to store the decoded event and */ 
  395.       /* a switch that tells which of the two buffers to use.  Returns a */
  396.       /* pointer to the next raw <MTrk event> in the track or 0 if the   */
  397.       /* track is exhausted.                                             */
  398.       ptrack[x] = DecodeEvent( ptrack[x] , pDTrack[x] , masterswitch );
  399.       if(pDTrack[x]->nexclock < lowclock && ptrack[x])
  400.          /* Find the first event */
  401.          lowclock=pDTrack[x]->nexclock;
  402.    }
  403.  
  404.    /*-----------------------------------*/
  405.    /* Transfer first events to A buffer */
  406.    /*-----------------------------------*/
  407.    for(x=0;x<trackct;x++)
  408.    {
  409.       if((pDTrack[x]->nexclock==lowclock) && ptrack[x])
  410.       {
  411.          /* Transfer event to parse buffer and handle successor */
  412.          y=transfer(pDTrack[x],masterswitch,y);
  413.          z=1;
  414.          while(z==1)
  415.          {
  416.             ptrack[x]=DecodeEvent(ptrack[x],pDTrack[x],masterswitch);
  417.             /* Next delta is zero... */
  418.             if( !(pDTrack[x]->absdelta) && ptrack[x])
  419.             {
  420.                y=transfer(pDTrack[x],masterswitch,y);
  421.             }
  422.             else {z=0;}
  423.          }
  424.       }
  425.    }
  426.    ylength[masterswitch]=y;
  427.    fillclock[masterswitch]=(LONG)(tfactor*lowclock);
  428.  
  429.  
  430.    /*------------------------------------*/
  431.    /* Transfer second events to B buffer */
  432.    /*------------------------------------*/
  433.    y=0;
  434.    masterswitch=1L;
  435.    lowclock=0xffffffff;
  436.    for(x=0;x<trackct;x++)
  437.    {
  438.       if(pDTrack[x]->nexclock < lowclock && ptrack[x])
  439.          lowclock=pDTrack[x]->nexclock;
  440.    }
  441.  
  442.    for(x=0;x<trackct;x++)
  443.    {
  444.       if(pDTrack[x]->nexclock==lowclock && ptrack[x])
  445.       {
  446.          /* Transfer event to parse buffer and handle successor */
  447.          y=transfer(pDTrack[x],masterswitch,y);
  448.          z=1;
  449.          while(z==1)
  450.          {
  451.             ptrack[x]=DecodeEvent(ptrack[x],pDTrack[x],masterswitch);
  452.             /* Next delta is zero... */
  453.             if( !(pDTrack[x]->absdelta) && ptrack[x])
  454.             {
  455.                y=transfer(pDTrack[x],masterswitch,y);
  456.             }
  457.             else {z=0;}
  458.          }
  459.       }
  460.    }
  461.  
  462.    ylength[masterswitch]=y;
  463.    fillclock[masterswitch]=(LONG)(tfactor*lowclock);
  464.  
  465.    /*-----------------------------------------------------*/
  466.    /* Priority Must Be Above Intuition and Graphics Stuff */
  467.    /*-----------------------------------------------------*/ 
  468.    mt=FindTask(NULL);
  469.    oldpri=SetTaskPri(mt,21);
  470.  
  471.  
  472.    /*---------------------------------------------------------------*/ 
  473.    /* Set up a PlayerInfo and a Conductor to get timing information */
  474.    /*---------------------------------------------------------------*/ 
  475.    midiSignal = AllocSignal(-1L);
  476.    if(midiSignal==-1) 
  477.        kill("Couldn't allocate a signal bit\n");
  478.  
  479.    pPlayerInfo=CreatePlayer( PLAYER_Name,       "SMF Player PlayerInfo",
  480.                              PLAYER_Conductor,  "SMF Player's Conductor",
  481.                              PLAYER_SignalTask, mt,
  482.                              PLAYER_AlarmSigBit,midiSignal,
  483.                              TAG_END);
  484.    if(!pPlayerInfo)
  485.        kill("Can't create a PlayerInfo\n");
  486.  
  487.    /*---------------------------------*/
  488.    /* Make sure the clock is stopped. */
  489.    /*---------------------------------*/
  490.    res = SetConductorState( pPlayerInfo, CLOCKSTATE_STOPPED, 0L );
  491.    if(res!=0)
  492.        kill("Couldn't stop conducotr\n");
  493.  
  494.    /*-------------------------------------------*/
  495.    /* Play the first batch of notes in Buffer A */
  496.    /*-------------------------------------------*/
  497.    if(ylength[masterswitch^1]!=0)
  498.       {
  499.       ParseMidi(pMidiLink,pfillbuf[masterswitch^1],
  500.                           ylength[masterswitch^1]);
  501.       }
  502.  
  503.    /*------------------------------------*/
  504.    /* and start the RealTime alarm clock */
  505.    /*------------------------------------*/
  506.    res = SetConductorState( pPlayerInfo, CLOCKSTATE_RUNNING, 0L );
  507.    if(res!=0)
  508.        kill("Couldn't start conducotr\n");
  509.  
  510.    /*---------------------*/
  511.    /* and set the alarm.  */
  512.    /*---------------------*/
  513.    timerr = SetPlayerAttrs( pPlayerInfo, 
  514.                             PLAYER_AlarmTime, fillclock[masterswitch],
  515.                             PLAYER_Ready, TRUE,
  516.                             TAG_END);
  517.    if(!timerr)
  518.        kill("Couldn't set player attrs\n");
  519.  
  520.    /*-----------------*/
  521.    /* MAIN EVENT LOOP */
  522.    /*-----------------*/   
  523.    while(donecount<trackct)
  524.    {
  525.       masterswitch ^= 1L;
  526.       y=0;
  527.       lowclock=0xffffffff;
  528.  
  529.       /*------------------------------------------------*/  
  530.       /* Get events from track into DecTrack structures */
  531.       /*------------------------------------------------*/
  532.       for(x=0;x<trackct;x++)
  533.       {
  534.          if((pDTrack[x]->nexclock < lowclock) && ptrack[x])
  535.             lowclock=pDTrack[x]->nexclock;
  536.       }
  537.  
  538.       /*-----------------------------------*/
  539.       /* Transfer events to current buffer */
  540.       /*-----------------------------------*/
  541.       for(x=0;x<trackct;x++)
  542.       {
  543.          if((pDTrack[x]->nexclock==lowclock) && ptrack[x])
  544.          {
  545.             /* Transfer event to parse buffer and handle successor */
  546.             y=transfer(pDTrack[x],masterswitch,y);
  547.             z=1;
  548.             while(z==1)
  549.             {
  550.                ptrack[x]=DecodeEvent(ptrack[x],pDTrack[x],masterswitch);
  551.                /* Next delta is zero... */
  552.                if( !(pDTrack[x]->absdelta) && ptrack[x] )
  553.                {
  554.                   y=transfer(pDTrack[x],masterswitch,y);
  555.                }
  556.                else {z=0;}
  557.             }
  558.          }
  559.       }
  560.  
  561.       ylength[masterswitch]=y;
  562.       fillclock[masterswitch]=(LONG)(tfactor*lowclock);
  563.  
  564.  
  565.       /*---------------------------------------------------------------*/
  566.       /* Wait() for the CAMD alarm or a CTRL-C keypress from the user. */
  567.       /*---------------------------------------------------------------*/
  568.       if(timerr)
  569.          wakeup=Wait(1L<< midiSignal | SIGBREAKF_CTRL_C);
  570.  
  571.       if(wakeup & SIGBREAKF_CTRL_C)  
  572.       {
  573.          /* Restore Priority */
  574.          if(mt!=NULL) SetTaskPri(mt,oldpri);
  575.          /* And Quit */
  576.          kill("User abort\n");
  577.       }
  578.  
  579.       /*-------------------------------*/
  580.       /* Start the next set of events  */
  581.       /*-------------------------------*/
  582.       if(ylength[masterswitch^1]!=0)
  583.          {
  584.          ParseMidi(pMidiLink,pfillbuf[masterswitch^1],
  585.                              ylength[masterswitch^1]);
  586.          }
  587.  
  588.       /*---------------------*/
  589.       /* and set the alarm.  */
  590.       /*---------------------*/
  591.       timerr = SetPlayerAttrs( pPlayerInfo, 
  592.                                PLAYER_AlarmTime, fillclock[masterswitch],
  593.                                PLAYER_Ready, TRUE,
  594.                                TAG_END);
  595.       if(!timerr)
  596.           kill("Couldn't set player attrs 2\n");
  597.    }
  598.  
  599.    /*-----------------------------------*/
  600.    /* Finish off the last set of events */
  601.    /*-----------------------------------*/
  602.    masterswitch^=1L;
  603.  
  604.    if(timerr)
  605.       wakeup=Wait(1L<< midiSignal | SIGBREAKF_CTRL_C);
  606.  
  607.  
  608.    if(ylength[masterswitch^1]!=0)
  609.       {
  610.       ParseMidi(pMidiLink,pfillbuf[masterswitch^1],
  611.                        ylength[masterswitch^1]);
  612.       }
  613.  
  614.    /* Restore Priority */
  615.    if(mt!=NULL) SetTaskPri(mt,oldpri);
  616.  
  617.    kill("AOK\n");
  618. }
  619.  
  620.  
  621. /*------------------------------*/
  622. /* Cleanup and return resources */
  623. /*------------------------------*/
  624. void
  625. kill(char *killstring)
  626. {
  627.    if(midiSignal != -1)FreeSignal(midiSignal);
  628.    if(pPlayerInfo)     DeletePlayer(pPlayerInfo);
  629.    if(pData)           FreeMem(pData,sizeDTrack);
  630.    if(pMidiLink)       RemoveMidiLink(pMidiLink);
  631.    if(pMidiNode)       DeleteMidi(pMidiNode);
  632.    if(RealTimeBase)    CloseLibrary(RealTimeBase);
  633.    if(CamdBase)        CloseLibrary(CamdBase);
  634.    if(smfhandle)       Close(smfhandle);
  635.    if(smfdata)         FreeMem(smfdata,smfdatasize);
  636.    printf(killstring);
  637.    exit(0);
  638. }
  639.  
  640.  
  641. /*--------------------------------------------------*/  
  642. /* Translate from raw track data to a decoded event */
  643. /*--------------------------------------------------*/  
  644. UBYTE *DecodeEvent(UBYTE *ptdata,struct DecTrack *pDTdata, ULONG deswitch)
  645. {
  646.    LONG status;
  647.    ULONG length;
  648.    BOOL skipit;
  649.  
  650.    pDTdata->absdelta = 0L;
  651.    pDTdata->playable = TRUE; /* Assume it's playble and not a meta-event */
  652.  
  653.    skipit=FALSE;
  654.    do
  655.    {
  656.       /* is this track all used up? */             
  657.       if( ptdata >= pDTdata->endmarker )
  658.       {
  659.          printf("Track done,...\n");
  660.          donecount++;
  661.          return(0L);
  662.       }
  663.       else /* there is more data to handle in the track */
  664.       {
  665.          /* Decode delta */
  666.          pDTdata->absdelta += ComVarLen(ptdata);
  667.          pDTdata->nexclock+= pDTdata->absdelta;
  668.  
  669.          /* Update pointer to event following delta */
  670.          while(*ptdata>127)
  671.             {
  672.             ptdata++;
  673.             }
  674.          ptdata++;
  675.  
  676.          if(*ptdata>127) /* Event with status ($80-$FF): decode new status */  
  677.          {
  678.             status=*ptdata;
  679.          
  680.             pDTdata->status=status;
  681.             pDTdata->rstatus=0;    /* No running status was used */
  682.      
  683.             ptdata++;
  684.             
  685.             if(status<240) /* Handle easy status $8x - $Ex */
  686.             {
  687.                skipit=FALSE;
  688.                pDTdata->d1 = *ptdata;
  689.                if(status<192 || status>223) /* $80-$BF, $E0-$EF: 2 data bytes */
  690.                {
  691.                   ptdata++;
  692.                   pDTdata->d2=*ptdata;
  693.                }
  694.                else pDTdata->d2=0;            /* $C0-$DF: 1 data byte */
  695.             }
  696.             else /* Status byte $Fx, system exclusive or meta events  */
  697.             {
  698.                skipit=TRUE;
  699.                
  700.                if(status==0xff)            /* It's a meta event ($ff) */
  701.                {
  702.                   pDTdata->metatype=*ptdata;
  703.               
  704.                   ptdata++; /* Now pointing at length byte */
  705.  
  706.                   if(pDTdata->metatype==81)
  707.                   {
  708.                      /* Tempo change event.  There are 60 milllion    */
  709.                      /* microseconds in a minute.  The lower 3 bytes  */ 
  710.                      /* pointed to by ptdata give the microseconds    */
  711.                      /* per MIDI quarter note. So, assuming a quarter */
  712.                      /* note gets the beat, this equation             */
  713.                      /*      60000000L /                              */
  714.                      /*          ( *((ULONG *)ptdata) & 0x00ffffff ) )*/
  715.                      /* gives beats per minute.                       */
  716.  
  717.                      tfactor = changetempo( *((ULONG *)ptdata) & 0x00ffffff );
  718.  
  719.                      /* Tempo event is not playable.  This prevents the */
  720.                      /* event from being transferred to the play buffer */
  721.                      pDTdata->playable = FALSE; 
  722.  
  723.                      /* Even though this event can't be played, it     */
  724.                      /* takes some time and should not be skipped.     */
  725.                      skipit=FALSE;
  726.                   }
  727.                   length=ComVarLen(ptdata);
  728.                   pDTdata->absmlength=length;
  729.                   while(*ptdata>127)ptdata++;
  730.  
  731.                   ptdata+=length;
  732.                }
  733.                else if(status==0xf0 || status==0xf7) /* It's a sysex event */
  734.                {
  735.                   pDTdata->metatype=0xff;
  736.                   printf("Sysex event");
  737.                   length=ComVarLen(ptdata);
  738.                   pDTdata->absmlength=length;
  739.                   while(*ptdata>127)ptdata++;
  740.  
  741.                   ptdata+=length;
  742.                }
  743.                else        /* It's an unkown event type ($f1-$f6, $f8-$fe) */
  744.                {
  745.                   pDTdata->metatype=0xff;
  746.                   printf("Unknown event"); 
  747.                }
  748.             }
  749.          }
  750.          else /* Event without status ($00-$7F): use running status */
  751.          {
  752.             skipit=FALSE;
  753.             /* Running status data bytes */
  754.             status=pDTdata->status;
  755.             pDTdata->rstatus=status;
  756.  
  757.             if(status==0)
  758.                kill("Bad file, data bytes without initial status.\n");
  759.  
  760.             pDTdata->d1=*ptdata;
  761.  
  762.             if(status<192 || status>223) /* $80-$BF, $E0-$EF: 2 data bytes */
  763.             {
  764.                ptdata++;
  765.                pDTdata->d2=*ptdata;
  766.             }
  767.             else pDTdata->d2=0;         /* $C0-$DF: 1 data byte */
  768.          }
  769.          ptdata++;
  770.       }
  771.    }
  772.    while(skipit);
  773.  
  774.    return(ptdata);
  775. }
  776.  
  777.  
  778. /*------------------------------------------------------------*/
  779. /* Transfer the decoded event to the fill buffer for playback */
  780. /*------------------------------------------------------------*/
  781. LONG
  782. transfer(struct DecTrack *pDT,ULONG mswitch,LONG ylen)
  783. {
  784.    ULONG y;
  785.    y=(ULONG )ylen;
  786.  
  787.    if (pDT->playable)
  788.    {
  789.       if(pDT->rstatus == lastRSchan)
  790.       { 
  791.          /* Running status so just put the 2 data bytes in buffer */
  792.          *(pfillbuf[mswitch] + y)=pDT->d1;
  793.          y++;
  794.          *(pfillbuf[mswitch] + y)=pDT->d2;
  795.       }
  796.       else 
  797.       {
  798.          /* New status so store status and data bytes */
  799.          *(pfillbuf[mswitch] + y)=pDT->status;
  800.          y++;
  801.          *(pfillbuf[mswitch] + y)=pDT->d1;
  802.          if(pDT->status<192 || pDT->status>223)
  803.          {
  804.             y++;
  805.             *(pfillbuf[mswitch] + y)=pDT->d2;
  806.          }
  807.          lastRSchan=pDT->status;     
  808.       }
  809.       y++;
  810.    }
  811.    return((LONG)y);
  812. }
  813.  
  814.  
  815. /*-------------------------------------------------------------------------*/
  816. /* Handle the Change Tempo event.   With the realtime.library, the timing  */
  817. /* quantum is fixed at 1.66 milliseconds (600 Hz).  This makes handling    */
  818. /* of SMF tempo pretty rough.  Tempo is controlled through a ULONG integer */
  819. /* named tfactor which is used to multiply the time deltas in the SMF      */
  820. /* file.  We can't multiply the time deltas by a fractional amount and     */
  821. /* that makes tempo handling even rougher.  For correct tempo handling the */
  822. /* clock quantum has to be variable and controlled by this program.        */
  823. /*-------------------------------------------------------------------------*/
  824. ULONG
  825. changetempo(ULONG ctbpm)
  826. {
  827.    ULONG timefac,timerem,tickfreq;
  828.  
  829.    tickfreq=(ULONG)((struct RealTimeBase *)RealTimeBase)->TickFreq;
  830.  
  831.    /* CAMD uses 1.66ms quantum for 600 ticks/sec                      */
  832.    /* SMF uses one tick = quarter note/pSMFHeader->Division           */
  833.    /* Hence, microseconds per delta in SMF is given by ctbpm/division */
  834.    /* and BPM is given by 60,000,000/ctbpm.                           */
  835.    timefac=(tickfreq * (ctbpm/division)) / 1000000;
  836.    timerem=(tickfreq * (ctbpm/division)) % 1000000;
  837.    if ( timerem >= 500000 )
  838.       timefac++;
  839.  
  840.    return(timefac);
  841. }
  842.  
  843.  
  844.  
  845.